<script setup lang="ts">
import { ref, watchEffect } from "vue";
import { rafTimeout } from "../../hooks/tools";
interface Collapse {
  key?: string | number; // 对应activeKey，如果没有传入key属性，则默认使用数据索引(0,1,2...)绑定
  header?: string; // 面板标题 string | slot
  text?: string; // 面板内容 string | slot
}
interface Props {
  collapseData: Collapse[]; // 折叠面板数据，可使用 v-slot 替换对应索引的 header 和 text
  activeKey?: number[] | number | string[] | string | null; // (v-model)当前激活 tab 面板的 key
  copyable?: boolean; // 是否可复制面板内容
  lang?: string; // 面板右上角固定内容，例如标识language string | slot
  fontSize?: number; // 面板标题和内容的字体大小
  headerFontSize?: number; // 面板标题字体大小，优先级高于fontSize
  textFontSize?: number; // 面板内容字体大小，优先级高于fontSize
  showArrow?: boolean; // 是否展示面板上的箭头
}
const props = withDefaults(defineProps<Props>(), {
  collapseData: () => [],
  activeKey: null,
  copyable: false,
  lang: "",
  fontSize: 14,
  headerFontSize: 0,
  textFontSize: 0,
  showArrow: true,
});
watchEffect(
  () => {
    const len = props.collapseData.length;
    if (len) {
      getCollapseHeight(len); // 获取各个面板内容高度
    }
  },
  { flush: "post" }
);
const text = ref();
const collapseHeight = ref<any[]>([]);
function getCollapseHeight(len: number) {
  for (let n = 0; n < len; n++) {
    collapseHeight.value.push(text.value[n].offsetHeight);
  }
}
const emits = defineEmits(["update:activeKey", "change"]);
function dealEmit(value: any) {
  emits("update:activeKey", value);
  emits("change", value);
}
function onClick(key: number | string) {
  if (activeJudge(key)) {
    if (Array.isArray(props.activeKey)) {
      const res = (props.activeKey as any[]).filter((actKey) => actKey !== key);
      dealEmit(res);
    } else {
      dealEmit(null);
    }
  } else {
    if (Array.isArray(props.activeKey)) {
      dealEmit([...props.activeKey, key]);
    } else {
      dealEmit(key);
    }
  }
}
function activeJudge(key: number | string): boolean {
  if (Array.isArray(props.activeKey)) {
    return (props.activeKey as any[]).includes(key);
  } else {
    return props.activeKey === key;
  }
}
const copyTxt = ref("Copy");
function onCopy(index: number) {
  navigator.clipboard.writeText(text.value[index].innerText || "").then(
    () => {
      /* clipboard successfully set */
      copyTxt.value = "Copied";
      rafTimeout(() => {
        copyTxt.value = "Copy";
      }, 3000);
    },
    (err) => {
      /* clipboard write failed */
      copyTxt.value = err;
    }
  );
}
</script>
<template>
  <div class="m-collapse">
    <div
      class="m-collapse-item"
      :class="{ 'u-collapse-item-active': activeJudge(data.key || index) }"
      v-for="(data, index) in collapseData"
      :key="index"
    >
      <div class="u-collapse-header" @click="onClick(data.key || index)">
        <div
          class="u-header"
          :class="{ ml24: showArrow }"
          :style="`font-size: ${headerFontSize || fontSize}px;`"
        >
          <slot name="header" :header="data.header" :key="data.key || index">{{
            data.header || "--"
          }}</slot>
        </div>
        <icons
          v-if="showArrow"
          class="icon"
          :name="activeJudge(data.key || index) ? 'jian' : 'add1'"
        />
      </div>
      <div
        class="u-collapse-content"
        :class="{ 'u-collapse-copyable': copyable }"
        :style="`height: ${
          activeJudge(data.key || index) ? collapseHeight[index] : 0
        }px;`"
      >
        <div class="u-lang">
          <slot name="lang" :lang="lang" :key="data.key || index">{{
            lang
          }}</slot>
        </div>
        <div size="small" class="u-copy" @click="onCopy(index)">
          {{ copyTxt }}
        </div>
        <div
          ref="text"
          class="u-text"
          :style="`font-size: ${textFontSize || fontSize}px;`"
        >
          <slot name="text" :text="data.text" :key="data.key || index">
            <div v-for="(item, i) in data.text" :key="i" class="item-view">
              <div class="yuan"></div>
              <div class="yuan-tt">{{ item }}</div>
            </div>
          </slot>
        </div>
      </div>
    </div>
  </div>
</template>
<style lang="less" scoped>
.m-collapse {
  border-bottom: 0;
  .m-collapse-item {
    border-bottom: 1px solid #c7c7c7;
    &:last-child {
      .u-collapse-content {
        border-radius: 0 0 8px 8px;
      }
    }
    .u-collapse-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      position: relative;
      padding: 12px 0px;
      cursor: pointer;
      transition: all 0.3s;
      .u-arrow {
        width: 12px;
        height: 12px;
        top: 0;
        bottom: 0;
        margin: auto 0;
        fill: rgba(0, 0, 0, 0.88);
        transition: transform 0.3s;
      }
      .u-header {
        display: inline-block;
        font-size: 15px;
        font-family: PingFangSC-Regular, PingFang SC;
        font-weight: 400;
        color: #000000;
        line-height: 21px;
      }
    }
    .u-collapse-content {
      position: relative;
      height: 0;
      overflow: hidden;
      transition: height 0.3s;
      .u-lang {
        position: absolute;
        right: 10px;
        top: 6px;
        font-size: 14px;
        color: rgba(0, 0, 0, 0.38);
        opacity: 1;
        transition: opacity 0.3s;
      }
      .u-copy {
        position: absolute;
        right: 8px;
        top: 8px;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.3s;
      }
      .u-text {
        // padding: 9px 16px 10px;
        margin-left: 12px;
        font-size: 14px;
        font-family: PingFangSC-Regular, PingFang SC;
        font-weight: 400;
        color: #000000;
        line-height: 20px;
        white-space: pre-wrap;
      }
    }
    .u-collapse-copyable {
      &:hover {
        .u-lang {
          opacity: 0;
          pointer-events: none;
        }
        .u-copy {
          opacity: 1;
          pointer-events: auto;
        }
      }
    }
  }
  .u-collapse-item-active {
    .u-arrow {
      transform: rotate(90deg);
    }
    .u-collapse-content {
      padding-bottom: 50px;
    }
  }
  .item-view {
    // padding: 10px 0;
    padding-bottom: 25px;
    display: flex;
    align-items: center;
    .yuan {
      width: 5px;
      height: 5px;
      min-width: 5px;
      min-height: 5px;
      border-radius: 100%;
      background: #000000;
      margin-right: 8px;
    }
    .yuan-tt {
      flex: 1;
    }
  }
}
</style>
